var websock = null;
let rec; // After disconnection and reconnection, delay 5 seconds to re-create the WebSocket connection rec is used to store the code for delayed requests
let isConnect = false; // Connection identification to avoid duplicate connections
let connectCallBack = null;
let messageCallBack = null;
let closeCallBack = null


let connect = (wsurl, accessToken) => {
	try {
		if (isConnect) {
			return;
		}
		console.log("Connect WebSocket");
		websock = new WebSocket(wsurl);
		websock.onmessage = function (e) {
			let sendInfo = JSON.parse(e.data)
			if (sendInfo.cmd == 0) {
				heartCheck.start()
				// The connection is truly completed only after the login is successful
				connectCallBack && connectCallBack();
				console.log('WebSocket login successful')
			} else if (sendInfo.cmd == 1) {
				// Restart the heartbeat timing
				heartCheck.reset();
			} else {
				// Forward other messages
				console.log("Receive message: ", sendInfo);
				messageCallBack && messageCallBack(sendInfo.cmd, sendInfo.data)
			}
		}
		websock.onclose = function (e) {
			console.log('WebSocket Connection Closed')
			isConnect = false; //Modify the logo after disconnection
			closeCallBack && closeCallBack(e);
		}
		websock.onopen = function () {
			console.log("WebSocket connection successful");
			isConnect = true;
			// Send login command
			let loginInfo = {
				cmd: 0,
				data: {
					accessToken: accessToken
				}
			};
			websock.send(JSON.stringify(loginInfo));
		}

		// Callback method for connection errors
		websock.onerror = function () {
			console.log('WebSocket connection error')
			isConnect = false; // Disconnection modification flag
			reconnect(wsurl, accessToken);
		}
	} catch (e) {
		console.log("An attempt to create a connection failed");
		reconnect(wsurl, accessToken); // If you cannot connect to the webSocket, reconnect! The connection may not be established due to server redeployment or a temporary network outage.
	}
};

// Defining the reconnection function
let reconnect = (wsurl, accessToken) => {
	console.log("Try to reconnect");
	if (isConnect) {
		//If you are already connected, don't reconnect.
		return;
	}
	rec && clearTimeout(rec);
	rec = setTimeout(function () { // Delay reconnection for 5 seconds to avoid too many and too frequent reconnection requests
		connect(wsurl, accessToken);
	}, 15000);
};
// Set the connection to close
let close = (code) => {
	websock && websock.close(code);
};


// Heartbeat settings
let heartCheck = {
	timeout: 5000, //Send a heartbeat packet every time, here it is set to 20s
	timeoutObj: null, //Delayed sending of message object (create this object when starting heartbeat, and reset the object after receiving the message)
	start: function () {
		if (isConnect) {
			console.log('Sending WebSocket Heartbeats')
			let heartBeat = {
				cmd: 1,
				data: {}
			};
			websock.send(JSON.stringify(heartBeat))
		}
	},

	reset: function () {
		clearTimeout(this.timeoutObj);
		this.timeoutObj = setTimeout(function () {
			heartCheck.start();
		}, this.timeout);

	}
};



// The method actually called
let sendMessage = (agentData) => {
	if (websock.readyState === websock.OPEN) {
		// If ws is turned on
		websock.send(JSON.stringify(agentData))
	} else if (websock.readyState === websock.CONNECTING) {
		// If ws is in the open state, wait for 1 second and call again
		setTimeout(function () {
			sendMessage(agentData)
		}, 1000)
	} else {
		// If ws is not enabled, wait for 1 second and call agai
		setTimeout(function () {
			sendMessage(agentData)
		}, 1000)
	}
}

let onConnect = (callback) => {
	connectCallBack = callback;
}

let onMessage = (callback) => {
	messageCallBack = callback;
}


let onClose = (callback) => {
	closeCallBack = callback;
}

export {
	connect,
	reconnect,
	close,
	sendMessage,
	onConnect,
	onMessage,
	onClose,
}
